<?php
/**
 * Service.class.php
 * 
 * pdk Service基类
 * 
 * @author lsl <470663151@qq.com> 
 * @copyright Copyright (c) 2014 lsl8966 Software Studio
 * @link http://www.cnblogs.com/lsl8966
 * @version $Id: AutoLoad.class.php 1.0 2014-12-15 22:48:01Z lsl $
 * @package core
 * @since 1.0
 */

if (!defined('IN_PDK')){
     exit();
}

abstract class Service extends Base{
    protected $jsonObj;
    protected $returnJsonObj;
    /**
     * 视图实例化变量
     * 
     * @var object 
     */
     protected static $_view;
    /**
     * 配置文件内容临时存贮数组
     * 
     * @var array 
     */
     public static $_config = array();
    
    /**
     * xml配置文件内容临时存贮数组
     * 
     * @var array 
     */
     public static $_xml = array();
    
    /**
     * 扩展模块实例化对象存贮数组
     * 
     * @var object 
     */
     public static $_moduleNameArray = array();
       
    /**
     * 扩展类对象存贮数组
     * 
     * @var object 
     */
     public static $_extensionArray = array();
    
    /**
     * 构造函数

     * 用于初始化本类的运行环境,或对基本变量进行赋值
     * 
     * @access public 
     * @return boolean 
     */
     public function __construct(){
        
         // 时区设置,默认为中国(北京时区)
        date_default_timezone_set(PDK_TIMEZONE);
        
         // 设置项目系统session的存放目录
        $sessionDir = CACHE_DIR . 'session';
         if (is_dir($sessionDir) && is_writable($sessionDir)){
             session_save_path($sessionDir);
         }
        
         // 关闭魔术变量，提高PHP运行效率.
        if (get_magic_quotes_runtime()){
             @set_magic_quotes_runtime(0);
         }
        
         // 将全局变量进行魔术变量处理,过滤掉系统自动加上的'\'.
        if (get_magic_quotes_gpc()){
             $_POST = $this -> stripSlashes($_POST);
             $_GET = $this -> stripSlashes($_GET);
             $_SESSION = $this -> stripSlashes($_SESSION);
             $_COOKIE = $this -> stripSlashes($_COOKIE);
         }
        
        // 回调函数,实例化控制器(Controller)时,执行所要补充的程序
        $this -> init();
     }
    
    /**
     * 获取并分析$_GET数组某参数值

     * 获取$_GET的全局超级变量数组的某参数值,并进行转义化处理，提升代码安全.注:参数支持数组
     * 
     * @access public 
     * @param string $string 所要获取$_GET的参数
     * @param string $defaultParam 默认参数, 注:只有$string不为数组时有效
     * @return string $_GET数组某参数值
     */
     public static function get($string, $defaultParam = null){
         return Request :: get($string, $defaultParam);
     }
    
    /**
     * 获取并分析$_POST数组某参数值

     * 获取$_POST全局变量数组的某参数值,并进行转义等处理，提升代码安全.注:参数支持数组
     * 
     * @access public 
     * @param string $string 所要获取$_POST的参数
     * @param string $defaultParam 默认参数, 注:只有$string不为数组时有效
     * @return string $_POST数组某参数值
     */
     public static function post($string, $defaultParam = null){
        
         return Request :: post($string, $defaultParam);
     }
    
    /**
     * 批量获取$_POST或$_GET数组参数值
     * 
     * @access public 
     * @param string $optionName 请求类型: post, get, request
     * @return array 
     */
     public static function requestVars($optionName = 'post'){
        
         return Request :: requestVars($optionName);
     }
    
    /**
     * 获取并分析 $_GET或$_POST全局超级变量数组某参数的值

     * 获取并分析$_POST['参数']的值 ，当$_POST['参数']不存在或为空时，再获取$_GET['参数']的值。
     * 
     * @access public 
     * @param string $string 所要获取的参数名称
     * @param string $defaultParam 默认参数, 注:只有$string不为数组时有效
     * @return string $_GET或$_POST数组某参数值
     */
     public static function getParams($string, $defaultParam = null){
        
         return Request :: getParams($string, $defaultParam);
     }

    /**
     * stripslashes()的同功能操作
     *
     * @access protected
     * @param string $string 所要处理的变量
     * @return mixed 变量
     */
    protected static function stripSlashes($string){

        // 参数分析.
        if (!$string){
            return false;
        }

        if (!is_array($string)){
            return stripslashes($string);
        }

        foreach ($string as $key => $value){
            $string[$key] = self :: stripSlashes($value);
        }

        return $string;
    }

    /**
     * 优雅输出print_r()函数所要输出的内容
     * 
     * 用于程序调试时,完美输出调试数据,功能相当于print_r().当第二参数为true时(默认为:false),功能相当于var_dump()。
       注:本方法一般用于程序调试
     * 
     * @access public 
     * @param array $data 所要输出的数据
     * @param boolean $option 选项:true或 false
     * @return array 所要输出的数组内容
     */
     public static function dump($data, $option = false){
        
         // 当输出print_r()内容时
        if(!$option){
             echo '<pre>';
             print_r($data);
             echo '</pre>';
             }else{
             ob_start();
             var_dump($data);
             $output = ob_get_clean();
            
             $output = str_replace('"', '', $output);
             $output = preg_replace('/\]\=\>\n(\s+)/m', '] => ', $output);
            
             echo '<pre>', $output, '</pre>';
        }
        
         exit;
     }
    
    /**
     * 单例模式实例化一个Model对象
     * 
     * 单例模式实现化一个model对象. 初次实例化某Model后, 当第二次实例化时则直接调用初次实现化的结果(object)
     * 
     * @access public 
     * @param string $modelName 所要实例化的Modle名称
     * @return object 实例化后的对象
     */
     public static function model($modelName){
        
         // 参数判断
        if (!$modelName){
             return false;
        }
        
         // 分析model名
        $modelName = ucfirst(trim($modelName)) . 'Model';
        
         return pdk ::singleton($modelName);
     }
    
    /**
     * 加载并单例模式实例化扩展模块.
     * 
     * 注：这里所调用的扩展模板要放在项目extension目录里的modules子目录中
     * 
     * @access public 
     * @param string $moduleName 模块名称
     * @return object 扩展模块的实例化对象
     */
     public static function module($moduleName){
        
         // 参数判断.
        if (!$moduleName){
             return false;
        }
        
         if (!isset(self :: $_moduleNameArray[$moduleName])){
             // 加载扩展模块的引导文件
            $module_file = MODULE_DIR . $moduleName . DIRECTORY_SEPARATOR;
             $_module_name = ucfirst(strtolower($moduleName));
             $module_file .= $_module_name . 'Module.class.php';
            
             self :: import($module_file);
            
             self :: $_moduleNameArray[$moduleName] = self :: instance($_module_name . 'Module');
         }
        
         return self :: $_moduleNameArray[$moduleName];
     }
    
    /**
     * 加载并单例模式实例化扩展类.
     * 
     * 注：这里所调用的扩展模板要放在项目extension目录里
     * 
     * @access public 
     * @param string $moduleName 模块名称
     * @return object 扩展模块的实例化对象
     */
	 public static function extension($extensionName){        
         // 参数判断.
        if (!$extensionName){
            return false;
        }
        
        if (!isset(self :: $_extensionArray[$extensionName])){
            // 加载扩展模块的引导文件
			//$file = EXTENSION_DIR.strtolower($extensionName).'.class.php';    		
			self :: $_extensionArray[$extensionName] = self :: instance($extensionName);                   
        }
        	
        return self :: $_extensionArray[$extensionName];
     }
	 
    /**
     * 第六部分:文件的加载, 等同于PHP函数include_once()
     * 
     * @author lsl 
     * @version 1.0 2010-10-21
     */
    
    /**
     * 静态加载文件

     * 相当于inclue_once()
     * 
     * @access public 
     * @params string $fileName 所要加载的文件
     * @return void 
     */
     public static function import($fileName){
         // 参数判断
         if (!$fileName){
             return false;
         }
         // 判断文件是不是项目扩展目录里的
         $fileUrl = ((strpos($fileName, '/') !== false) || (strpos($fileName, '\\') !== false)) ? realpath($fileName) : realpath(EXTENSION_DIR . $fileName . '.class.php');
         return pdk ::loadFile($fileUrl);
     }
    
    /**
     * 静态加载项目设置目录(config目录)中的配置文件
     * 
     * 加载项目设置目录(config)中的配置文件,当第一次加载后,第二次加载时则不再重新加载文件
     * 
     * @access public 
     * @param string $fileName 所要加载的配置文件名 注：不含后缀名
     * @return mixed 配置文件内容
     */
     public static function getConfig($key=null){
         // 参数分析.
         if (!isset(self :: $_config[$key])){
             $file   = new file();
             $l_file1 = $file->readDir(CONFIG_PATH, array('.cvs', '.svn', '.git', '.xml'));
             $l_file2 = $file->readDir(CONFIG_DIR, array('.cvs', '.svn', '.git', '.xml'));
             if(in_array('db.ini.php',$l_file1) && in_array('db.ini.php',$l_file2)){
                 foreach($l_file1 as $k=>$v){
                     if($v = 'db.ini.php'){
                         unset($l_file1[$k]);
                     }
                 }
             }
             //取include目录下的config
             foreach ($l_file1 as $file_name) {
                 if (is_dir(CONFIG_PATH.$file_name)){
                     continue;
                 }
                 if (!is_file(CONFIG_PATH.$file_name)){
                     self :: halt('The config file:' . $file_name . ' is not exists!');
                 }
                 $conf = include CONFIG_PATH.$file_name;
                 if (is_array(self :: $_config) && is_array($conf)) {
                     self :: $_config = array_merge(self :: $_config, $conf);
                 }
             }
             //取app目录下的config
             foreach ($l_file2 as $file_name) {

                 if (!is_file(CONFIG_DIR.$file_name)){
                     self :: halt('The config file:' . $file_name . ' is not exists!');
                 }

                 $conf = include CONFIG_DIR.$file_name;

                 if (is_array(self :: $_config) && is_array($conf)) {
                     self :: $_config = array_merge(self :: $_config, $conf);
                 }
             }
         }

         if ($key!=null&&isset(self :: $_config[$key])) {
             return self :: $_config[$key];
         }else{
             return self :: $_config;
         }
     }
    

    /**
     * Ajax调用返回
     * 
     * 返回json数据,供前台ajax调用
     * 
     * @param int $status 返回数组,支持数组
     * @param array $msg 返回数组,支持数组
     * @param array $data 返回数组,支持数组
     * @return string
     */
     public function ajax($status = 200,$msg = null,$data = null){
         $result = array();
         $result['service'] = isset($this->jsonObj->service)?$this->jsonObj->service:"";
         $result['op_type'] = isset($this->jsonObj->service)?$this->jsonObj->service:"";
         $result['code'] = $status;
         $result['msg']  = is_null($msg)?http::$_httpStatus[$status]:$msg;
         if(is_array($data)){
             $result = array_merge($result,$data);
         }
         $result['task_id']  = isset($this->jsonObj->task_id)?$this->jsonObj->task_id:"";
         $result['time']  = time();
//         http::httpStatus($status);
         $returnObj = json_encode($result);
         header("Content-Type:application/json; charset=utf-8");
         header("Content-Length:".strlen($returnObj));
 	    $this->__requestLog($msg,$returnObj,$status);
         $this->returnJsonObj = json_decode($returnObj);
         echo $returnObj;exit;
    }
    
   private function __requestLog($msg,$returnObj,$status){
	    if(!defined('LOG_REQUEST') || !LOG_REQUEST) return;
        $request_json = json_encode($this->jsonObj);
        $flag = 1;
        if($flag == 1){
            $log_data1 = "input:".$request_json."\r";
            $log_data1 .= "output:".$returnObj."\r";
            Log::write($log_data1,'info',strtolower(pdk::getAppName().'.'.$this->jsonObj->api_key.'.'.pdk::getControllerName()).'.json');
            $api_request_model = Controller::createMode('db_sys','t_sys_api_request_list');
            $log_data = array(
                'interface_name'=>$this->jsonObj->service,
                'app_key'=>$this->jsonObj->api_key,
                'user_id'=>$this->jsonObj->user_id,
                'create_time'=>date("Y-m-d H:i:s",$GLOBALS['_beginTime']),
                'update_time'=>date("Y-m-d H:i:s"),
                'm'=>$this->jsonObj->m,
                'input_params'=>$request_json,
                'output_params'=>$returnObj,
                'respones_code'=>$status,
                'respones_msg'=>$msg,
                'ver'=>$this->jsonObj->ver,
                'ip_addr'=>http::getIp(),
                'client_type'=>$this->jsonObj->client_type,
                'response_duration'=>microtime(true)-$GLOBALS['_beginTime'],
            );
            if($this->jsonObj->map){
                $map = json_encode($this->jsonObj->map);
                $log_data['map'] = $map?$map:'';
            }
            if($this->jsonObj->ord){
                $ord = json_encode($this->jsonObj->ord);
                $log_data['ord'] = $ord?$ord:'';
            }
            $api_request_model -> insert($log_data);
        }
    }


    /**
     * 前函数

     * 用于添加Action Method执行前的程序处理,相当于构造函数(被构造函数所调用)
     * 
     * @access public 
     * @return void 
     */
     protected function init(){
		 //Log::write("DATA:::".json_encode($_REQUEST),'info',"post.data".'.json');
         $jPack = "";
         if(isset($_POST["json"])){
             $jPack = $_POST["json"];
         }
         if(isset($_GET["json"])){
             $jPack = $_GET["json"];
         }
         if($jPack){
             $jPack = urldecode($jPack);
             $jPack = stripcslashes($jPack);//过滤特殊字符
         }
         $jPack = str_replace("\\", '\\\\', $jPack);
         Log::write($jPack,'info',pdk::getAppName().'.'.pdk::getControllerName().'.json');
         $this->jsonObj = json_decode($jPack);
         if(is_null($this->jsonObj)){
             $this->ajax(40000);
             return false;
         } else {
             return true;
         }
     }


    /**
     * 类型转换
     * @param $list
     * @return mixed
     */
    protected function typeValueToString($list){
        if (count($list)==count($list, 1)) {
            //一位数组
            foreach($list as $key=>$val){
                if(count(self::$_extensionArray['o']['table_info'][$key]['commentEX'])){
                    $list[$key] = self::$_extensionArray['o']['table_info'][$key]['commentEX'][$val];
                }
            }
        } else {
            //二维数组
            foreach($list as $k=>$row ){
                foreach($row as $key=>$val){
                    if(count(self::$_extensionArray['o']['table_info'][$key]['commentEX'])){
                        $list[$k][$key] = self::$_extensionArray['o']['table_info'][$key]['commentEX'][$val];
                    }
                    if(is_null($list[$k][$key])){
                        $list[$k][$key] = ''; //保证传至客户端都没有NULL值
                    }
                }
            }
        }
        return $list;
    }


    /**
     * 解析where参数
     * @param null $fiels
     * @return string
     */
    protected  function parseWhere($fiels = null){
        $map = $this->get('map')?$this->get('map'):$this->post('map');
        if($map){
            $map_obj = json_decode(urldecode($map));
        }else {
            $map_obj = $this->jsonObj->map;
        }
        if($map_obj){
            $maps = array();
            if($map_obj){
                foreach($map_obj as $row ){
                    $s = trim($row[2]);
                    if($fiels && !in_array(trim($row[1]),$fiels)){
                        continue;
                    }
                    $map = ' ';
                    if(trim($row[1]) == 'eq'){
                        if(is_string($s)){
                            $map .= $row[0] ." = '".$s."'";
                        } else{
                            $map .= $row[0] .'='.trim($row[2]);
                        }
                    }
                    if(trim($row[1]) == 'gt'){
                        if(is_string($s)){
                            $map .= $row[0] ." > '".$s."'";
                        } else{
                            $map .= $row[0] .' > '.trim($row[2]);
                        }
                    }
                    if(trim($row[1]) == 'gte'){
                        $map .= $row[0] .'>='.trim($row[2]);
                    }
                    if(trim($row[1]) == 'in' && trim($row[2]) != ''){
                        $map .= $row[0] .' in ('.trim($row[2].')');
                    }
                    if(trim($row[1]) == 'nin' && trim($row[2]) != ''){
                        $map .= $row[0] .' not in ('.trim($row[2].')');
                    }
                    if(trim($row[1]) == 'lt'){
                        if(is_string($s)){
                            $map .= $row[0] ." < '".$s."'";
                        } else{
                            $map .= $row[0] .'<'.trim($row[2]);
                        }
                    }
                    if(trim($row[1]) == 'lte'){
                        $map .= $row[0] .'<='.trim($row[2]);
                    }
                    if(trim($row[1]) == 'neq'){
                        $s = trim($row[2]);
                        if(is_string($s)){
                            $map .= $row[0] ." != '".$row[2]."'";
                        } else{
                            $map .= $row[0] .'!='.trim($row[2]);
                        }
                    }
                    if(trim($row[1]) == 'between'){
                        $map .= $row[0] ." between {$row[2]} and {$row[3]}";
                    }
                    if(trim($row[1]) == 'like'){
                        $map .= $row[0] .' like "%'.trim($row[2].'%"');
                    }
                    if($map != ''){
                        $maps[] = $map;
                    }
                }
            }
            $where = implode(' AND ', $maps);
        }
        return ($where=='')?" 1=1 ":$where;
    }

    /**
     * 解析order参数
     * @param null $fiels
     * @return string
     */
    protected  function parseOrder($fiels = null){
        $map = $this->get('ord')?$this->get('ord'):$this->post('ord');
        if($map){
            $map_obj = json_decode(urldecode($map));
        }else {
            $map_obj = $this->jsonObj->ord;
        }
        $orders = array();
        if($map_obj){
            $orders = (array) $map_obj;
        }
        return is_array($orders)?$orders:array();
    }

}
